怎么也没想到,我的个人网站数据库竟然被黑掉了。所有的库都被删掉,只留有一个勒索信息表。查看数据库日志,除了 drop 库和新建了一个 mysqlbackups 用户之外,并没发现其他记录。(已经撕票,还让我交钱,没有武德啊)。不过庆幸,只是侵入了数据库,并未发现服务器有异常,而且数据库的binlog文件都在。下面就尝试通过日志文件进行恢复。

截图1

关于 binlog

二进制日志 binlog 是 MySQL 最重要的日志之一,记录了对数据库的常见增删改查,索引,表的操作记录(DDL和DML);binlog 主要用于复制和数据恢复。关于复制,之前写过一个简单的示例 使用Docker实现简单的MySQL主从复制。本篇的内容主要介绍数据恢复。

binlog 默认开启,SET SQL_LOG_BIN=1开启,SET SQL_LOG_BIN=0关闭(重启生效)。

show master status 可以查看当前正在写入的 binlog 文件。binlog 的磁盘路径,默认应该位于 /var/lib/mysql 下,可以在数据库配置文件中自定义。(binlog 在生产环境作为重要的日志文件,一定要特别注意保存和维护)。

切换到 binlog 所在目录,可以看到日志文件分为两类。

  1. **.index (index后缀)记录所有有效的的二进制文件,index 就是 binlog 的索引目录文件。
  2. *.0000 (数字后缀) 记录数据库所有的 DDL 和 DML 语句事件。

日志恢复

可以使用 mysqlbinlog 命令去查看 binlog。注意:mysqlbinlog是 shell 命令,而不是 MySQL 命令

mysqlbinlog mysql-bin.000001可以进行直接查看。当然,很少的情况会这样使用,因为通常 binlog 很大,会导致终端窗口无限滚动。

出现了错误?

直接执行 mysqlbinlog mysql-bin.000001 可能出现错误:mysqlbinlog: unknown variable 'default-character-set=utf8',这个问题可以通过带上参数 --no-defaults 解决;
mysqlbinlog --no-defaults mysql-bin.000002

下面所有的 mysqlbinlog 命令基于我本地服务器的环境,默认都带上 --no-defaults

这就要求我们进行有目的地查询;比如手误删除了某个表中的数据,可以以该表的表名 table1 作为关键词进行查询;知道某个具体的自增主键的ID,也可以通过ID作为关键词。

mysqlbinlog --no-defaults mysql-bin.000001 | grep table1 -C 3; 这里通过 grep 查询关键词 table1,其中 -C 3 表示查看关键词匹配行的上下三行内容。同理,-B 3打印匹配行的前3行(B=before);-A 3打印匹配行的后3行(A=after)。

截图2

上图是查询关键词 INSERT_ID=2734961 的终端截图。

这里有两个重要的信息(图中划红线的位置):position 事件位置和事件时间。下面几个参数可以用来框选日志的范围。

  • –start-datetime=开始时间

  • –stop-datetime=结束时间

  • –start-position=开始位置

  • –stop-position=结束位置

  • –database=数据库名称

mysqlbinlog --no-defaults --database=db --start-position=34926815 --stop-position=181096090 mysql-bin.000001 | /usr/bin/mysql -uroot -ppwd -v db 事件位置在 34926815 和 181096090 之间的脚本重新执行(恢复)到指定账户的数据库,只执行该数据库的事件 db 库有关的脚本。

总结

这次暂不清除什么原因导致数据库账户泄露,但终归是因为没有良好的数据库权限管理的习惯,而导致这次的"损失"。折腾一下午,数据算是恢复了。亡羊补牢,这里列出几个常见的tips:

  1. 数据库的 root 账户只能在数据库所在服务器进行本地使用,不得远程登录。
  2. 平时的数据库连接工具采用一个库一个账户的方式,防止鸡蛋放在一个篮子里。
  3. 接口服务的数据库连接账号只予以增删改查的权限 select,insert,update,delete。因为代码都在云端托管,万一第三方出现信息泄漏(gitlab出现过账户信息泄漏),也能将风险劲量降低。

另外,对数据库的定期备份也是一个必须操作。因为这次好在数据库数据量不大,恢复也未太费功夫。倘若生产环境数年的数据被删除,即使可以通过日志进行恢复,恢复过程中的宕机损失也不能忽视。有了定期备份,需要恢复数据量的减少也会大大减少恢复本身所需的时间,从而减小意外事故带来的业务损失。

最后,害人之心不可有,防人之心不可无。